#include "fixed64_tool.h"
#include "fixed64.h"
#include <stdio.h>
#include <cmath>
#include <cstring>

bool save(const char* path, const char* funcName,FPRaw* datas, int size)
{
	char buf[256];
	memset(buf, 0, sizeof(buf));
	sprintf(buf,"%s/%slooktbl.cpp", path, funcName);

	FILE* fp = fopen(buf, "wb");
	if (!fp)
		return false;

	const char* header = "#include \"fixed64.h\"\n";
	int len = (int)strlen(header);
	fwrite(header, len, 1, fp);

	memset(buf, 0, sizeof(buf));
	sprintf(buf, "static const FPRaw g_table_%s[FIXED_LOOKTABLE_UP_CNT]={\n",funcName);
	len = (int)strlen(buf);
	fwrite(buf, len, 1, fp);

	int n = 0;
	for (int i = 0; i < size; ++i)
	{
		if(i % 5 == 0)
			fwrite("\t", strlen("\t"), 1, fp);

		memset(buf, 0, sizeof(buf));
		if(i == size - 1)
			sprintf(buf, "%lld", datas[i]);
		else
			sprintf(buf, "%lld,", datas[i]);
		n += (int)fwrite(buf, strlen(buf),1, fp);

		if ((i + 1) % 5 == 0)
			fwrite("\n", strlen("\n"), 1, fp);
	}

	fwrite("};\n", strlen("};\n"), 1, fp);

	fflush(fp);
	fclose(fp);
	return n == size;
}

bool genrate_sin_function(const char* path)
{
	fixed64 perPi = (fixed64::PI * fixed64::_0_50) >> FIXED_LLOKTABLE_BIT;
	double pp = perPi;
	FPRaw* values = new FPRaw[FIXED_LOOKTABLE_UP_CNT];
	memset(values, 0, sizeof(values));
	for (int i = 0; i < FIXED_LOOKTABLE_UP_CNT; ++i)
	{
		double sinv = sinf(perPi * i);
		FPRaw v = (FPRaw)(sinv * ((FPRaw(1)) << fixed64::f_bit_cnt) + 0.5);
		values[i] = v;
	}
	bool r = save(path, "sin", values, FIXED_LOOKTABLE_UP_CNT);
	delete[] values;
	return r;
}

bool genrate_cos_function(const char* path)
{
	fixed64 perPi = (fixed64::PI * fixed64::_0_50) >> FIXED_LLOKTABLE_BIT;
	double pp = perPi;
	FPRaw* values = new FPRaw[FIXED_LOOKTABLE_UP_CNT];
	memset(values, 0, sizeof(values));
	for (int i = 0; i < FIXED_LOOKTABLE_UP_CNT; ++i)
	{
		double cosv = cosf(perPi * i);
		FPRaw v = (FPRaw)(cosv * ((FPRaw(1)) << fixed64::f_bit_cnt) + 0.5);
		values[i] = v;
	}
	bool r = save(path, "cos", values, FIXED_LOOKTABLE_UP_CNT);
	delete[] values;
	return r;
}

bool genrate_tan_function(const char* path)
{
	fixed64 perPi = (fixed64::PI * fixed64::_0_50) >> FIXED_LLOKTABLE_BIT;
	double pp = perPi;
	FPRaw* values = new FPRaw[FIXED_LOOKTABLE_UP_CNT];
	memset(values, 0, sizeof(values));
	for (int i = 0; i < FIXED_LOOKTABLE_UP_CNT; ++i)
	{
		double tanv = tanf(perPi * i);
		FPRaw v = (FPRaw)(tanv * ((FPRaw(1)) << fixed64::f_bit_cnt) + 0.5);
		values[i] = v;
	}
	bool r = save(path, "tan", values, FIXED_LOOKTABLE_UP_CNT);
	delete[] values;
	return r;
}

bool genrate_arctan_function(const char* path)
{
	fixed64 perPi = (fixed64::PI * fixed64::_0_50) >> FIXED_LLOKTABLE_BIT;
	double pp = perPi;
	FPRaw* values = new FPRaw[FIXED_LOOKTABLE_UP_CNT];
	memset(values, 0, sizeof(values));
	for (int i = 0; i < FIXED_LOOKTABLE_UP_CNT; ++i)
	{
		double tanv = tanf(perPi * i);
		FPRaw v = (FPRaw)(tanv * ((FPRaw(1)) << fixed64::f_bit_cnt) + 0.5);
		values[i] = v;
	}
	bool r = save(path, "atan", values, FIXED_LOOKTABLE_UP_CNT);
	delete[] values;
	return r;
}

bool genrate(const char* path)
{
	bool r = genrate_cos_function(path);
	if (!r)
		return false;
	r = genrate_sin_function(path);
	if (!r)
		return false;
	r = genrate_arctan_function(path);
	if (!r)
		return false;
	return true;
}